<template>
  <view
    class="calendar-container"
    :class="{
      'mode-single': mode === 'single',
      'calendar-collapsed': !isExpanded,
      'calendar-collapsing': isCollapsing,
    }"
    @touchstart="handleTouchStart"
    @touchend="handleTouchEnd"
    @touchmove="handleTouchMove"
    @transitionend="handleTransitionEnd"
  >
    <!-- 日历头部控制栏 -->
    <view class="calendar-header" v-if="showHeader">
      <view class="btn prev-month" @click="prevMonth">
        <text class="icon">〈</text>
      </view>
      <view class="month-title">{{ currentYearMonth }}</view>
      <view class="btn next-month" @click="nextMonth">
        <text class="icon">〉</text>
      </view>
    </view>

    <!-- 星期标题栏 -->
    <view class="weekdays" :class="{ 'weekdays-collapsed': !isExpanded }">
      <text v-for="(day, index) in weekdays" :key="index" class="weekday">{{
        day
      }}</text>
    </view>

    <!-- 日期网格 -->
    <view class="days-container">
      <view class="days">
        <!-- 月视图：显示整个月的日期 -->
        <template v-if="isExpanded">
          <view
            v-for="(dayInfo, index) in calendarDays"
            :key="`month-day-${index}`"
            :class="{
              day: true,
              'prev-month': dayInfo.monthType === 'prev',
              'current-month': dayInfo.monthType === 'current',
              'next-month': dayInfo.monthType === 'next',
              'active-day': dayInfo.isAvailable,
              'unavailable-day': !dayInfo.isAvailable,
              today: dayInfo.isToday,
              'single-date': mode === 'single' && isStartDate(dayInfo),
              'start-date': mode === 'range' && isStartDate(dayInfo),
              'end-date': mode === 'range' && isEndDate(dayInfo),
              'in-range': mode === 'range' && isInRange(dayInfo),
            }"
            @click="!dayInfo.isAvailable ? null : selectDate(dayInfo)"
          >
            <view class="day-content">{{ dayInfo.day }}</view>
            <!-- 添加日期提示点 -->
            <view v-if="dayInfo.hasIndicator" class="day-indicators-container">
              <view
                v-for="(indicator, index) in dayInfo.indicators"
                :key="index"
                class="day-indicator"
                :class="[`indicator-${indicator.type || 'default'}`]"
              ></view>
            </view>
            <!-- 如果是范围的开始或结束日期，添加指示文字 -->
            <text
              v-if="mode === 'range' && isStartDate(dayInfo)"
              class="indicator"
              >开始</text
            >
            <text
              v-if="mode === 'range' && isEndDate(dayInfo)"
              class="indicator"
              >结束</text
            >
          </view>
        </template>

        <!-- 周视图：只显示当前周的日期 -->
        <template v-else>
          <view
            v-for="(dayInfo, index) in getWeekDays()"
            :key="`week-day-${index}`"
            :class="{
              day: true,
              'prev-month': dayInfo.monthType === 'prev',
              'current-month': dayInfo.monthType === 'current',
              'next-month': dayInfo.monthType === 'next',
              'active-day': dayInfo.isAvailable,
              'unavailable-day': !dayInfo.isAvailable,
              today: dayInfo.isToday,
              'single-date': mode === 'single' && isStartDate(dayInfo),
              'start-date': mode === 'range' && isStartDate(dayInfo),
              'end-date': mode === 'range' && isEndDate(dayInfo),
              'in-range': mode === 'range' && isInRange(dayInfo),
            }"
            @click="!dayInfo.isAvailable ? null : selectDate(dayInfo)"
          >
            <view class="day-content">{{ dayInfo.day }}</view>
            <!-- 添加日期提示点 -->
            <view v-if="dayInfo.hasIndicator" class="day-indicators-container">
              <view
                v-for="(indicator, index) in dayInfo.indicators"
                :key="index"
                class="day-indicator"
                :class="[`indicator-${indicator.type || 'default'}`]"
              ></view>
            </view>
            <!-- 周日历 开始或结束日期，不需要添加指示文字 -->
          </view>
        </template>
      </view>
    </view>

    <!-- 收缩指示器 -->
    <view class="expand-indicator" @click="toggleCalendarExpand"> </view>

    <!-- 日期选择器底部 -->
    <view class="calendar-footer" v-if="showFooter && isExpanded">
      <view class="date-info">
        <text v-if="mode === 'single' && startDate"
          >已选择：{{ formatDate(startDate) }}</text
        >
        <template v-else>
          <text v-if="startDate">开始：{{ formatDate(startDate) }}</text>
          <text v-if="startDate && endDate">至</text>
          <text v-if="endDate">结束：{{ formatDate(endDate) }}</text>
        </template>
      </view>
      <view class="action-buttons">
        <view class="btn reset-btn" @click="resetSelection">重置</view>
        <view class="btn confirm-btn" @click="confirmSelection">确定</view>
      </view>
    </view>
  </view>
</template>

<script>
/**
 * 日期选择器组件
 * 支持单日选择或日期范围选择，适用于多种场景
 *
 * 特点：
 * 1. 支持单日/范围两种选择模式
 * 2. 支持展开/收缩状态切换
 * 3. 支持左右滑动切换月份（展开状态）或周（收缩状态）
 * 4. 灵活的配置选项
 */
import * as dateHelpers from "@/utils/dateHelpers.js";
const nowDate = dateHelpers.getToday();

export default {
  name: "DateRangeCalendar",
  props: {
    // 选择模式: 'single'表示单选一天, 'range'表示选择日期范围
    mode: {
      type: String,
      default: "single",
      validator: (value) => ["single", "range"].includes(value),
    },
    // 最小可选日期
    minDate: {
      type: [Date, String, Object],
      default: function () {
        let date = nowDate.setFullYear(nowDate.getFullYear() - 1); // 默认一年内
        return date;
      },
    },
    // 最大可选日期
    maxDate: {
      type: [Date, String, Object],
      default: function () {
        let date = nowDate.setFullYear(nowDate.getFullYear() + 1); // 默认一年内
        return date;
      },
    },
    // 指定"今天"的日期，默认为系统当前日期
    todayDate: {
      type: [Date, String, Object],
      default: function () {
        return nowDate;
      },
    },
    // 初始选择的开始日期
    initialStartDate: {
      type: [Date, String, Object],
      default: null,
    },
    // 初始选择的结束日期
    initialEndDate: {
      type: [Date, String, Object],
      default: null,
    },
    // 是否允许选择同一天作为开始和结束
    allowSameDay: {
      type: Boolean,
      default: false,
    },
    // 不可选择的日期数组
    disabledDates: {
      type: Array,
      default: function () {
        return [];
      },
    },
    // 是否显示底部操作栏
    showFooter: {
      type: Boolean,
      default: false,
    },
    // 是否显示顶部操作栏
    showHeader: {
      type: Boolean,
      default: false,
    },

    // 切换月份时是否自动选择第一天
    autoSelectFirstDay: {
      type: Boolean,
      default: true,
    },
    // 带有指示器的日期数据，格式为 [{date: '2023-12-15', type: 'primary'}, ...]
    markedDates: {
      type: Array,
      default: function () {
        return [];
      },
    },
    // 是否允许同一天显示多个指示器
    multipleIndicators: {
      type: Boolean,
      default: false,
    },
    // 每天最多显示的指示器数量
    maxIndicatorsPerDay: {
      type: Number,
      default: 3,
    },
  },
  data() {
    // 处理props中可能的日期格式问题
    const processedMinDate = dateHelpers.handleMiniProgramDate(this.minDate);
    const processedMaxDate = dateHelpers.handleMiniProgramDate(this.maxDate);
    const processedInitialStartDate = dateHelpers.handleMiniProgramDate(
      this.initialStartDate
    );
    const processedInitialEndDate = dateHelpers.handleMiniProgramDate(
      this.initialEndDate
    );
    const processedTodayDate = dateHelpers.handleMiniProgramDate(
      this.todayDate
    );
    // 使用处理后的日期初始化(是否有设定'今天')
    const today = processedTodayDate || nowDate;

    return {
      calendarDays: [],
      currentMonth: today.getMonth(),
      currentYear: today.getFullYear(),
      isExpanded: true,
      weekdays: ["日", "一", "二", "三", "四", "五", "六"],
      startDate: processedInitialStartDate,
      endDate: processedInitialEndDate,
      selectionMode: "start",
      currentWeekIndex: 0,
      isCollapsing: false,
      isWeekViewMonthChange: false,

      // 内部处理后的props
      internalMinDate: processedMinDate,
      internalMaxDate: processedMaxDate,
      internalTodayDate: processedTodayDate,
      // 添加时间戳属性
      minTimestamp: processedMinDate ? processedMinDate.getTime() : null,
      maxTimestamp: processedMaxDate ? processedMaxDate.getTime() : null,
      todayTimestamp: processedTodayDate ? processedTodayDate.getTime() : null,
      // 添加触摸相关变量
      touchStartX: 0,
      touchStartY: 0,
      touchThreshold: 50, // 触发滑动的阈值
      isTouchMoved: false, // 标记是否发生了移动
      touchDirection: "", // 记录滑动方向：horizontal或vertical
    };
  },
  created() {
    // 使用合适的方式初始化日期
    const date = this.startDate || new Date();
    this.currentMonth = date.getMonth();
    this.currentYear = date.getFullYear();

    // 生成日历数据
    this.generateCalendarDays();
  },
  watch: {
    // 监听月份变化，重新生成日历数据
    currentMonth() {
      this.$nextTick(() => {
        // 重新生成日历数据
        this.generateCalendarDays();

        // 仅在非周视图滑动引起的月份变化时更新当前周索引和选择日期
        if (!this.isWeekViewMonthChange) {
          if (this.startDate && this.isDateInCurrentMonth(this.startDate)) {
            this.updateCurrentWeekIndex(this.startDate);
          } else if (this.autoSelectFirstDay) {
            this.updateCurrentWeekIndex(
              dateHelpers.createDateForMP(
                this.currentYear,
                this.currentMonth,
                1
              )
            );
          } else {
            this.updateCurrentWeekIndex(this.internalTodayDate);
          }
        }

        // 重置标志位
        this.isWeekViewMonthChange = false;
      });
    },
    // 监听年份变化，重新生成日历数据
    currentYear() {
      this.$nextTick(() => {
        // 重新生成日历数据
        this.generateCalendarDays();

        // 仅在非周视图滑动引起的年份变化时更新当前周索引和选择日期
        if (!this.isWeekViewMonthChange) {
          if (this.startDate && this.isDateInCurrentMonth(this.startDate)) {
            this.updateCurrentWeekIndex(this.startDate);
          } else if (this.autoSelectFirstDay) {
            this.updateCurrentWeekIndex(
              dateHelpers.createDateForMP(
                this.currentYear,
                this.currentMonth,
                1
              )
            );
          } else {
            this.updateCurrentWeekIndex(this.internalTodayDate);
          }
        }
      });
    },
    // 监听开始日期变化
    startDate(newVal) {
      if (newVal) {
        this.$nextTick(() => {
          // 只需要月日历情况下实时刷新 周索引
          if (!this.isWeekViewMonthChange) {
            // 周日历情况下不属于这里去实时刷新 切换的时候已刷新
            this.updateCurrentWeekIndex(newVal);
          }
        });
      } else {
        // 如果选择被清空，默认显示今天日期所在行
        this.$nextTick(() => {
          const validTodayDate = dateHelpers.isValidDate(this.internalTodayDate)
            ? this.internalTodayDate
            : dateHelpers.getToday();
          // 只需要月日历情况下实时刷新 周索引
          if (this.isExpanded) {
            this.updateCurrentWeekIndex(validTodayDate);
          }
        });
      }
    },
    // 监听结束日期变化
    endDate(newVal) {
      // 不需要更新时间戳，直接使用日期对象
    },
    // 监听指示器日期变化
    markedDates: {
      handler(newVal) {
        this.$nextTick(() => {
          // 重新生成日历数据
          this.generateCalendarDays(4);
        });
      },
      immediate: true,
      deep: true,
    },
    // 监听todayDate prop的变化
    todayDate: {
      handler(newVal) {
        // 处理新的todayDate值
        const processedDate = dateHelpers.handleMiniProgramDate(newVal);
        if (dateHelpers.isValidDate(processedDate)) {
          // 更新内部today日期 注意不再直接使用todayDate
          this.internalTodayDate = processedDate;
          this.todayTimestamp = processedDate.getTime();

          // 重新生成日历数据以反映新的"今天"
          this.generateCalendarDays();

          this.$nextTick(() => {
            // 如果没有选择日期，可能需要更新当前周索引
            if (!this.startDate && this.isExpanded) {
              this.updateCurrentWeekIndex(processedDate);
            }
          });

          console.log("更新today为:", this.formatDate(processedDate));
        } else {
          console.warn("提供的todayDate无效，将继续使用当前值");
        }
      },
      immediate: false, // 不需要立即触发，mounted中已处理初始值
    },
  },
  computed: {
    // 当前月份的显示标题：例如"2023年12月"
    currentYearMonth() {
      return `${this.currentYear}年${this.currentMonth + 1}月`;
    },

    // 获取当前月的天数数组数据
    daysInMonth() {
      let days = dateHelpers.getDaysInMonth(
        this.currentYear,
        this.currentMonth
      );
      // 返回一个从1开始递增到当月天数的数组
      return Array.from({ length: days }, (_, index) => index + 1);
    },

    // 当前月的总天数（数值）
    daysCount() {
      return dateHelpers.getDaysInMonth(this.currentYear, this.currentMonth);
    },

    // 当前月第一天是星期几（0是星期日，6是星期六）
    firstDayOfMonth() {
      return dateHelpers.getFirstDayOfMonth(
        this.currentYear,
        this.currentMonth
      );
    },

    // 今天的日期信息
    today() {
      // 确保todayDate是Date实例，否则使用当前日期
      let date =
        this.internalTodayDate instanceof Date
          ? this.internalTodayDate
          : dateHelpers.getToday();
      return {
        year: date.getFullYear(),
        month: date.getMonth(),
        date: date.getDate(),
      };
    },
  },
  mounted() {
    // 处理小程序环境中日期格式转换的问题

    console.log("处理初始日期", this.initialStartDate);

    // 处理初始日期
    if (this.initialStartDate) {
      this.startDate = dateHelpers.handleMiniProgramDate(this.initialStartDate);
      // 将日志改为调试级别
      console.debug("[DateRangeCalendar] 初始化startDate:", this.startDate);
    }

    if (this.initialEndDate) {
      this.endDate = dateHelpers.handleMiniProgramDate(this.initialEndDate);
      // 将日志改为调试级别
      console.debug("[DateRangeCalendar] 初始化endDate:", this.endDate);
    }

    // 处理props中可能的无效日期
    if (!dateHelpers.isValidDate(this.internalTodayDate)) {
      console.warn(
        "DateRangeCalendar: 提供的todayDate不是有效的Date对象，将使用当前日期"
      );
    }

    // 根据选择的日期初始化当前周索引
    this.initCurrentWeekIndex();
  },

  methods: {
    // 日期工具函数 - 比较两个日期是否是同一天
    isSameDay(date1, date2) {
      return dateHelpers.isSameDay(date1, date2);
    },
    // 获取上个月的天数
    getPrevMonthDays() {
      return dateHelpers.getPrevMonthDays(this.currentYear, this.currentMonth);
    },

    // 判断日期是否在当前显示的月份内
    isDateInCurrentMonth(date) {
      return dateHelpers.isDateInYearMonth(
        date,
        this.currentYear,
        this.currentMonth
      );
    },

    // 检查某天是否是开始日期
    isStartDate(data) {
      if (!this.startDate) return false;
      let { day, month, year } = data;
      // 确保输入的day是数字
      const numDay = Number(day);
      if (isNaN(numDay)) return false;

      // 如果提供了month和year，使用它们进行比较
      // 否则默认使用currentMonth和currentYear
      const monthToCheck =
        month !== undefined ? Number(month) : this.currentMonth;
      const yearToCheck = year !== undefined ? Number(year) : this.currentYear;

      return (
        this.startDate.getDate() === numDay &&
        this.startDate.getMonth() === monthToCheck &&
        this.startDate.getFullYear() === yearToCheck
      );
    },

    // 检查某天是否是结束日期
    isEndDate(data) {
      if (!this.endDate) return false;
      let { day, month, year } = data;
      // 确保输入的day是数字
      const numDay = Number(day);
      if (isNaN(numDay)) return false;

      // 如果提供了month和year，使用它们进行比较
      // 否则默认使用currentMonth和currentYear
      const monthToCheck = month !== undefined ? month : this.currentMonth;
      const yearToCheck = year !== undefined ? year : this.currentYear;

      return (
        this.endDate.getDate() === numDay &&
        this.endDate.getMonth() === monthToCheck &&
        this.endDate.getFullYear() === yearToCheck
      );
    },

    // 检查某天是否在选择的范围内 - 不再限制为当前月
    isInRange(data) {
      if (!this.startDate || !this.endDate) return false;
      let { day, month, year } = data;
      // 确保输入的day是数字
      const numDay = Number(day);
      if (isNaN(numDay)) return false;

      // 如果提供了month和year，使用它们创建日期对象
      // 否则默认使用currentMonth和currentYear
      const monthToCheck = month !== undefined ? month : this.currentMonth;
      const yearToCheck = year !== undefined ? year : this.currentYear;

      // 创建当前日期对象
      const currentDate = dateHelpers.createDateForMP(
        yearToCheck,
        monthToCheck,
        numDay
      );

      // 获取时间戳比较
      const currentTimestamp = currentDate.getTime();
      const startTimestamp = this.startDate.getTime();
      const endTimestamp = this.endDate.getTime();

      return (
        currentTimestamp > startTimestamp && currentTimestamp < endTimestamp
      );
    },

    // 选择日期（极简版 - 直接使用传入的日历数据）
    selectDate(dayInfo) {
      console.log("dayInfo", dayInfo);

      // 从dayInfo获取基本信息
      let { day, month, year } = dayInfo;

      // 创建日期对象用于可用性检查和存储
      const date = dateHelpers.createDateForMP(year, month, day);

      // 如果日期不可选，直接返回
      if (!this.isAvailableDayByDate(date)) {
        return;
      }

      // 如果选择的日期不在当前显示的月份，切换到对应的月份
      if (month !== this.currentMonth || year !== this.currentYear) {
        this.currentMonth = month;
        this.currentYear = year;
        // 使用$nextTick确保DOM更新后执行后续操作
        this.$nextTick(() => {
          this.processDateSelection(date, day, month, year);
        });
      } else {
        // 如果是当前月份，直接处理选择
        this.processDateSelection(date, day, month, year);
      }
    },

    // 抽取日期选择的处理逻辑
    processDateSelection(date, day, month, year) {
      // 计算选中日期在日历中的行号
      if (!this.isExpanded) {
        const dayPosition = this.firstDayOfMonth + day - 1;
        this.currentWeekIndex = Math.floor(dayPosition / 7);
      }

      // 单选模式
      if (this.mode === "single") {
        // 更新日期对象
        this.startDate = date;
        this.endDate = null;

        // 发出日期选择变化事件
        this.$emit("date-selection-change", {
          date: this.startDate,
          formattedDate: this.formatDate(date),
          year,
          month,
          day,
        });

        // 如果不显示底部栏，则选择后自动确认
        if (!this.showFooter) {
          this.confirmSelection();
        }

        return;
      }

      // 范围选择模式
      if (this.selectionMode === "start" || !this.startDate) {
        // 设置开始日期
        this.startDate = date;
        this.endDate = null;
        this.selectionMode = "end";
      } else if (this.selectionMode === "end") {
        const startTimestamp = this.startDate.getTime();
        const timestamp = date.getTime();

        // 如果所选日期早于开始日期，则将其设为开始日期
        if (timestamp < startTimestamp) {
          this.startDate = date;
          this.selectionMode = "end";
        }
        // 如果所选日期与开始日期是同一天
        else if (
          date.getDate() === this.startDate.getDate() &&
          date.getMonth() === this.startDate.getMonth() &&
          date.getFullYear() === this.startDate.getFullYear()
        ) {
          if (this.allowSameDay) {
            // 如果允许同一天，设为结束日期
            this.endDate = date;
            this.selectionMode = "start";

            // 如果不显示底部栏，则选择后自动确认
            if (!this.showFooter) {
              this.confirmSelection();
            }
          } else {
            // 如果不允许同一天，则重置开始日期
            this.startDate = date;
            this.selectionMode = "end";
          }
        }
        // 如果所选日期晚于开始日期，则将其设为结束日期
        else {
          this.endDate = date;
          this.selectionMode = "start";

          // 如果不显示底部栏，则选择后自动确认
          if (!this.showFooter) {
            this.confirmSelection();
          }
        }
      }

      // 发出日期选择变化事件
      this.$emit("date-selection-change", {
        startDate: this.startDate,
        endDate: this.endDate,
        formattedStartDate: this.formatDate(this.startDate),
        formattedEndDate: this.endDate ? this.formatDate(this.endDate) : "",
        startYear: this.startDate.getFullYear(),
        startMonth: this.startDate.getMonth(),
        startDay: this.startDate.getDate(),
        endYear: this.endDate ? this.endDate.getFullYear() : null,
        endMonth: this.endDate ? this.endDate.getMonth() : null,
        endDay: this.endDate ? this.endDate.getDate() : null,
      });

      // 更新日历选中状态
      this.updateSelectedStatus();
    },

    // 更新选中日期在日历中的行号
    updateSelectedDateRow(day) {
      if (!day) return;
      const dayPosition = this.firstDayOfMonth + day - 1;
      this.currentWeekIndex = Math.floor(dayPosition / 7);
    },

    // 重置选择
    resetSelection() {
      this.startDate = null;
      this.endDate = null;
      this.selectionMode = "start";

      // 将日历重置为当前月份
      const now = dateHelpers.isValidDate(this.internalTodayDate)
        ? this.internalTodayDate
        : dateHelpers.getToday();
      this.currentYear = now.getFullYear();
      this.currentMonth = now.getMonth();

      // 更新选中行为今天日期所在行
      this.$nextTick(() => {
        this.updateCurrentWeekIndex(now);
      });

      this.$emit("reset");
    },

    // 确认选择
    confirmSelection() {
      // 单日选择模式
      if (this.mode === "single") {
        if (!this.startDate) {
          uni.showToast({
            title: "请选择日期",
            icon: "none",
          });
          return;
        }

        // 确保返回有效的日期对象
        const validStartDate = dateHelpers.handleMiniProgramDate(
          this.startDate
        );

        const selection = {
          date: validStartDate,
          formattedDate: this.formatDate(validStartDate),
          timestamp: validStartDate.getTime(),
          year: validStartDate.getFullYear(),
          month: validStartDate.getMonth() + 1,
          day: validStartDate.getDate(),
        };

        this.$emit("confirm", selection);
        return;
      }

      // 范围选择模式
      if (!this.startDate) {
        uni.showToast({
          title: "请选择开始日期",
          icon: "none",
        });
        return;
      }

      if (!this.endDate && !this.allowSameDay) {
        uni.showToast({
          title: "请选择结束日期",
          icon: "none",
        });
        return;
      }

      // 确保返回有效的日期对象
      const validStartDate = dateHelpers.handleMiniProgramDate(this.startDate);
      const validEndDate = this.endDate
        ? dateHelpers.handleMiniProgramDate(this.endDate)
        : validStartDate;

      const selection = {
        startDate: validStartDate,
        endDate: validEndDate, // 如果允许同一天，则结束日期默认为开始日期
        formattedStartDate: this.formatDate(validStartDate),
        formattedEndDate: this.formatDate(validEndDate),
        // 添加额外数据便于接收方使用
        startTimestamp: validStartDate.getTime(),
        endTimestamp: validEndDate.getTime(),
        startYear: validStartDate.getFullYear(),
        startMonth: validStartDate.getMonth() + 1,
        startDay: validStartDate.getDate(),
        endYear: validEndDate.getFullYear(),
        endMonth: validEndDate.getMonth() + 1,
        endDay: validEndDate.getDate(),
        // 天数差
        days:
          Math.round(
            (validEndDate.getTime() - validStartDate.getTime()) /
              (24 * 60 * 60 * 1000)
          ) + 1,
      };

      this.$emit("confirm", selection);
    },

    // 处理触摸开始事件
    handleTouchStart(event) {
      this.touchStartX = event.touches[0].clientX;
      this.touchStartY = event.touches[0].clientY;
      this.isTouchMoved = false;
      this.touchDirection = "";
    },

    // 处理触摸结束事件
    handleTouchEnd(event) {
      // 如果没有开始触摸或没有移动，不处理
      if (!this.touchStartX || !this.isTouchMoved) return;

      const touchEndX = event.changedTouches[0].clientX;
      const touchEndY = event.changedTouches[0].clientY;

      // 计算水平和垂直方向的移动距离
      const deltaX = touchEndX - this.touchStartX;
      const deltaY = touchEndY - this.touchStartY;

      // 处理水平滑动 - 切换月份或周
      if (this.touchDirection === "horizontal") {
        // 如果水平滑动距离小，不处理
        if (Math.abs(deltaX) < this.touchThreshold) return;

        // 向左滑动切换到下一个月/周
        if (deltaX < 0) {
          if (this.isExpanded) {
            this.nextMonth();
          } else {
            this.nextWeek();
          }
        }
        // 向右滑动切换到上一个月/周
        else {
          if (this.isExpanded) {
            this.prevMonth();
          } else {
            this.prevWeek();
          }
        }
      }
      // 处理垂直滑动 - 展开或收缩日历
      else if (this.touchDirection === "vertical") {
        // 如果垂直滑动距离小，不处理
        if (Math.abs(deltaY) < this.touchThreshold) return;

        // 向下滑动(负deltaY) - 展开日历
        if (deltaY > 0 && !this.isExpanded) {
          console.log("向下滑动");

          this.expandCalendar();
        }
        // 向上滑动(正deltaY) - 收缩日历
        else if (deltaY < 0 && this.isExpanded) {
          console.log("向上滑动");

          this.collapseCalendar();
        }
      }

      // 重置触摸状态
      this.touchStartX = 0;
      this.touchStartY = 0;
      this.isTouchMoved = false;
      this.touchDirection = "";
    },

    // 处理触摸移动事件
    handleTouchMove(event) {
      // 记录当前触摸位置，用于计算滑动方向
      const currentX = event.touches[0].clientX;
      const currentY = event.touches[0].clientY;
      const deltaX = currentX - this.touchStartX;
      const deltaY = currentY - this.touchStartY;

      // 如果滑动距离过小，不处理
      if (Math.abs(deltaX) < 10 && Math.abs(deltaY) < 10) return;

      this.isTouchMoved = true;

      // 确定滑动方向 - 只在第一次移动时确定，之后保持不变
      if (!this.touchDirection) {
        this.touchDirection =
          Math.abs(deltaX) > Math.abs(deltaY) ? "horizontal" : "vertical";
      }

      // 防止滑动时页面滚动
      event.preventDefault();
    },

    // 更新选中日期行
    updateCurrentWeekIndex(date) {
      if (!date) return;

      // 检查日期是否在当前显示的月份内
      const isSameMonth =
        date.getMonth() === this.currentMonth &&
        date.getFullYear() === this.currentYear;
      // 如果日期在当前月份内，正常计算行号
      if (isSameMonth) {
        const day = date.getDate();
        const dayPosition = this.firstDayOfMonth + day - 1;

        this.currentWeekIndex = Math.floor(dayPosition / 7);
      } else {
        // 如果日期不在当前月份内，则尝试使用当前日期
        const day = dateHelpers.getToday();
        const isTodayInCurrentMonth =
          day.getMonth() === this.currentMonth &&
          day.getFullYear() === this.currentYear;

        if (isTodayInCurrentMonth) {
          // 如果今天在当前月份内，显示今天所在行
          const dayPosition = this.firstDayOfMonth + day.getDate() - 1;
          this.currentWeekIndex = Math.floor(dayPosition / 7);
        } else {
          // 否则默认显示第一行
          this.currentWeekIndex = 0;
        }
      }
    },

    // 切换到上一周
    prevWeek() {
      if (this.isExpanded) return;

      if (this.currentWeekIndex <= 0) {
        // 直接调用 prevMonth，它会处理月份切换和设置最后一周的逻辑
        this.prevMonth();
      } else {
        this.currentWeekIndex--;
        // 选择周的第一天（如果可用）
        this.selectWeekFirstDay(this.currentWeekIndex);
      }
    },

    // 切换到下一周
    nextWeek() {
      if (this.isExpanded) return;

      // 获取当前月总周数
      const totalWeeks = Math.ceil((this.firstDayOfMonth + this.daysCount) / 7);

      // 如果已经是当前月的最后一周
      if (this.currentWeekIndex >= totalWeeks - 1) {
        // 直接调用 nextMonth，它会处理月份切换和设置第一周的逻辑
        this.nextMonth();
      } else {
        // 在当前月内切换到下一周
        this.currentWeekIndex++;
        // 选择周的第一天（如果可用）
        this.selectWeekFirstDay(this.currentWeekIndex);
      }
    },

    // 检查某天是否在当前显示的周内
    isInVisibleWeek(day) {
      if (this.isExpanded) return true;

      // 计算当前月每一天在日历表中的实际位置
      // 第一天的位置是firstDayOfMonth，接着递增
      const dayPosition = this.firstDayOfMonth + day - 1;

      // 计算当前选中周的起始和结束位置
      const weekStartIndex = this.currentWeekIndex * 7;
      const weekEndIndex = weekStartIndex + 6;

      // 检查这一天是否在当前周范围内
      return dayPosition >= weekStartIndex && dayPosition <= weekEndIndex;
    },

    // 获取当前周的日期数据
    getWeekDays() {
      if (!this.calendarDays.length) {
        this.generateCalendarDays();
      }

      // 计算当前周的起始索引和结束索引
      const startIndex = this.currentWeekIndex * 7;
      const endIndex = startIndex + 7;

      // 检查索引是否超出范围
      if (startIndex >= this.calendarDays.length) {
        // 重置为第一周
        this.currentWeekIndex = 0;
        return this.calendarDays.slice(0, 7);
      }

      // 截取当前周的日期
      return this.calendarDays.slice(startIndex, endIndex);
    },

    // 检查日期是否被选中
    isSelectedDate(data) {
      if (!this.startDate) return false;
      let { day, month, year } = data;
      // 确保输入的day是数字
      const numDay = Number(day);
      if (isNaN(numDay)) return false;

      // 如果提供了month和year，使用它们进行比较
      // 否则默认使用currentMonth和currentYear
      const monthToCheck =
        month !== undefined ? Number(month) : this.currentMonth;
      const yearToCheck = year !== undefined ? Number(year) : this.currentYear;

      // 直接比较日期对象的年月日
      const isSameDay = (date) => {
        return (
          numDay === date.getDate() &&
          monthToCheck === date.getMonth() &&
          yearToCheck === date.getFullYear()
        );
      };

      // 单选模式
      if (this.mode === "single") {
        return isSameDay(this.startDate);
      }

      // 范围选择模式
      if (!this.endDate) return isSameDay(this.startDate);

      return isSameDay(this.startDate) || isSameDay(this.endDate);
    },

    // 切换日历展开/收缩状态
    toggleCalendarExpand() {
      if (this.isExpanded) {
        this.collapseCalendar();
      } else {
        this.expandCalendar();
      }
    },

    // 展开日历
    expandCalendar() {
      if (!this.isExpanded) {
        this.isExpanded = true;
        this.isCollapsing = false; // 重置收缩中状态
        this.$emit("calendar-expand");
      }
    },

    // 收缩日历转为周视图
    collapseCalendar() {
      if (this.isExpanded) {
        // 如果没有选中日期，使用当前可见的第一个可用日期
        if (!this.startDate) {
          // 寻找当前月的第一个可用日期
          for (let day = 1; day <= this.daysCount; day++) {
            const date = dateHelpers.createDateForMP(
              this.currentYear,
              this.currentMonth,
              day
            );
            if (this.isAvailableDayByDate(date)) {
              this.selectDate({
                day,
                month: this.currentMonth,
                year: this.currentYear,
              });
              break;
            }
          }
        }

        // 如果已选择日期，确保当前月份与所选日期的月份一致
        if (this.startDate) {
          // 确保日历显示的是选中日期的月份
          const selectedMonth = this.startDate.getMonth();
          const selectedYear = this.startDate.getFullYear();

          // 如果选中的日期不在当前显示的月份，切换到该月份
          if (
            selectedMonth !== this.currentMonth ||
            selectedYear !== this.currentYear
          ) {
            this.currentMonth = selectedMonth;
            this.currentYear = selectedYear;
            // 等待月份变化后再计算周索引
            this.$nextTick(() => {
              const selectedDay = this.startDate.getDate();
              const dayPosition = this.firstDayOfMonth + selectedDay - 1;
              this.currentWeekIndex = Math.floor(dayPosition / 7);
            });
          } else {
            // 当前月份与选中日期一致，直接计算周索引
            const selectedDay = this.startDate.getDate();
            const dayPosition = this.firstDayOfMonth + selectedDay - 1;
            this.currentWeekIndex = Math.floor(dayPosition / 7);
          }
        } else {
          // 无选中日期，默认显示第一周
          this.currentWeekIndex = 0;
        }

        // 设置收缩动画状态
        this.isCollapsing = true;

        // 使用定时器确保DOM更新后应用动画
        setTimeout(() => {
          // 更改展开状态
          this.isExpanded = false;
          this.$emit("calendar-collapse");
        }, 50);
      }
    },

    // 选择周的第一个可用日期
    selectWeekFirstAvailableDate(weekIndex = 1) {
      // 计算指定周的起始和结束日期索引
      const weekStartIndex = weekIndex * 7;
      const weekEndIndex = weekStartIndex + 6;

      console.log(
        `周${weekIndex}范围：${weekStartIndex}-${weekEndIndex}, firstDayOfMonth: ${this.firstDayOfMonth}`
      );

      // 1. 先检查当前月在目标周的日期
      // 计算目标周内第一天对应的当月日期
      const firstDayInWeek =
        weekStartIndex < this.firstDayOfMonth
          ? 1
          : weekStartIndex - this.firstDayOfMonth + 1;

      const lastDayInWeek = Math.min(
        this.daysCount,
        weekEndIndex - this.firstDayOfMonth + 1
      );

      console.log(`当月日期范围：${firstDayInWeek}-${lastDayInWeek}`);

      // 检查当月在目标周内的所有日期
      for (let day = firstDayInWeek; day <= lastDayInWeek; day++) {
        const date = dateHelpers.createDateForMP(
          this.currentYear,
          this.currentMonth,
          day
        );
        console.log(`检查当月日期: ${this.formatDate(date)}, 日期: ${day}`);
        if (this.isAvailableDayByDate(date)) {
          this.selectSpecificDate(date);
          return;
        }
      }

      // 2. 如果目标周跨月，可能包含上个月或下个月的日期
      // 检查上个月的日期（如果周的开始部分在上个月）
      if (weekStartIndex < this.firstDayOfMonth) {
        // 上个月年份和月份
        let prevYear = this.currentYear;
        let prevMonth = this.currentMonth - 1;
        if (prevMonth < 0) {
          prevMonth = 11;
          prevYear--;
        }

        // 获取上个月的天数
        const prevMonthDays = this.getPrevMonthDays();
        const daysFromPrevMonth = this.firstDayOfMonth - weekStartIndex;

        for (let i = 0; i < daysFromPrevMonth; i++) {
          const day = prevMonthDays - daysFromPrevMonth + i + 1;
          const date = dateHelpers.createDateForMP(prevYear, prevMonth, day);
          console.log(`检查上月日期: ${this.formatDate(date)}, 日期: ${day}`);
          if (this.isAvailableDayByDate(date)) {
            this.selectSpecificDate(date);
            return;
          }
        }
      }

      // 3. 检查下个月的日期（如果周的结束部分在下个月）
      if (weekEndIndex >= this.firstDayOfMonth + this.daysCount) {
        // 下个月年份和月份
        let nextYear = this.currentYear;
        let nextMonth = this.currentMonth + 1;
        if (nextMonth > 11) {
          nextMonth = 0;
          nextYear++;
        }

        const daysIntoNextMonth =
          weekEndIndex - (this.firstDayOfMonth + this.daysCount) + 1;

        for (let day = 1; day <= daysIntoNextMonth; day++) {
          const date = dateHelpers.createDateForMP(nextYear, nextMonth, day);
          console.log(`检查下月日期: ${this.formatDate(date)}, 日期: ${day}`);
          if (this.isAvailableDayByDate(date)) {
            this.selectSpecificDate(date);
            return;
          }
        }
      }

      // 4. 如果在目标周内没找到可用日期，选择月份的第一个可用日期
      console.log("没有找到可用日期，选择月份第一个可用日期");
      this.selectFirstDayOfMonth();
    },

    // 优先选择每周的第一天（如果可用）
    selectWeekFirstDay(weekIndex) {
      // 计算指定周的起始位置
      const weekStartIndex = weekIndex * 7;

      // 创建该周第一天的日期对象
      let firstDayDate;
      let firstDayYear, firstDayMonth, firstDayDay;

      // 判断周的第一天属于哪个月
      if (weekStartIndex < this.firstDayOfMonth) {
        // 周的第一天在上个月
        let prevMonth = this.currentMonth - 1;
        let prevYear = this.currentYear;
        if (prevMonth < 0) {
          prevMonth = 11;
          prevYear--;
        }

        // 计算日期
        const prevMonthDays = this.getPrevMonthDays();
        const day = prevMonthDays - (this.firstDayOfMonth - weekStartIndex) + 1;

        firstDayYear = prevYear;
        firstDayMonth = prevMonth;
        firstDayDay = day;
      } else if (weekStartIndex >= this.firstDayOfMonth + this.daysCount) {
        // 周的第一天在下个月
        let nextMonth = this.currentMonth + 1;
        let nextYear = this.currentYear;
        if (nextMonth > 11) {
          nextMonth = 0;
          nextYear++;
        }

        const day =
          weekStartIndex - (this.firstDayOfMonth + this.daysCount) + 1;

        firstDayYear = nextYear;
        firstDayMonth = nextMonth;
        firstDayDay = day;
      } else {
        // 周的第一天在当前月
        const day = weekStartIndex - this.firstDayOfMonth + 1;

        firstDayYear = this.currentYear;
        firstDayMonth = this.currentMonth;
        firstDayDay = day;
      }

      // 创建日期对象
      firstDayDate = dateHelpers.createDateForMP(
        firstDayYear,
        firstDayMonth,
        firstDayDay
      );
      console.log(`周${weekIndex}的第一天是: ${this.formatDate(firstDayDate)}`);

      // 检查第一天是否可用
      if (this.isAvailableDayByDate(firstDayDate)) {
        // 如果周的第一天可用，直接选择它
        this.selectSpecificDate(firstDayDate);
        return true;
      }

      console.log(`周${weekIndex}的第一天不可用，尝试其他日期`);

      // 如果第一天不可用，则调用原来的方法寻找该周的第一个可用日期
      this.selectWeekFirstAvailableDate(weekIndex);
      return false;
    },

    // 下个月的第一周的第一个可用日期（保持向后兼容）
    selectFirstWeekFirstAvailableDate() {
      // 调用通用方法，传入周索引1（第二周）
      this.selectWeekFirstAvailableDate(1);
    },

    // 处理过渡结束事件
    handleTransitionEnd(event) {
      // 只处理日历容器的过渡结束事件
      if (event.target === event.currentTarget && this.isCollapsing) {
        this.isCollapsing = false;
        this.$emit("calendar-collapse-end");
      }
    },
    // 通过日期对象检查日期是否可选
    isAvailableDayByDate(date) {
      if (!date) return false;

      // 日期是否在允许的范围内
      const dateYMD = dateHelpers.createDateForMP(
        date.getFullYear(),
        date.getMonth(),
        date.getDate()
      );

      // 检查是否在最小日期之前
      if (this.internalMinDate) {
        const minDateYMD = dateHelpers.createDateForMP(
          this.internalMinDate.getFullYear(),
          this.internalMinDate.getMonth(),
          this.internalMinDate.getDate()
        );
        if (dateYMD < minDateYMD) return false;
      }

      // 检查是否在最大日期之后
      if (this.internalMaxDate) {
        const maxDateYMD = dateHelpers.createDateForMP(
          this.internalMaxDate.getFullYear(),
          this.internalMaxDate.getMonth(),
          this.internalMaxDate.getDate()
        );
        if (dateYMD > maxDateYMD) return false;
      }

      // 检查是否在禁用日期列表中
      if (this.disabledDates && this.disabledDates.length > 0) {
        const formattedDate = this.formatDate(date);
        return !this.disabledDates.some((disabledDate) => {
          const formattedDisabled =
            typeof disabledDate === "string"
              ? disabledDate
              : this.formatDate(disabledDate);
          return formattedDisabled === formattedDate;
        });
      }

      return true;
    },

    // 初始化当前周索引，基于选中的日期
    initCurrentWeekIndex() {
      // 默认使用一个参考日期来确定当前周
      let referenceDate;

      // 如果有选择的开始日期，并且是有效的日期，使用它作为参考
      if (this.startDate && this.isAvailableDayByDate(this.startDate)) {
        referenceDate = this.startDate;
      } else {
        // 否则尝试使用今天的日期
        const today = dateHelpers.getToday();
        if (
          today.getFullYear() === this.currentYear &&
          today.getMonth() === this.currentMonth &&
          this.isAvailableDayByDate(today)
        ) {
          referenceDate = today;
        } else {
          // 如果今天不在当月或不可用，使用当月第一天
          referenceDate = dateHelpers.createDateForMP(
            this.currentYear,
            this.currentMonth,
            1
          );

          // 找到当月第一个可用的日期
          for (let day = 1; day <= this.daysCount; day++) {
            const date = dateHelpers.createDateForMP(
              this.currentYear,
              this.currentMonth,
              day
            );
            if (this.isAvailableDayByDate(date)) {
              referenceDate = date;
              break;
            }
          }
        }
      }

      // 基于参考日期计算周索引
      const refDay = referenceDate.getDate();
      const refDayPosition = this.firstDayOfMonth + refDay - 1;
      this.currentWeekIndex = Math.floor(refDayPosition / 7);

      // 确保calendarDays已生成
      if (!this.calendarDays.length) {
        this.generateCalendarDays();
      }
    },

    /**
     * 日期选择优先级处理说明：
     * 1. 用户点击日期选择 - 选择该日期，并更新当前周索引（如果在周视图中）
     * 2. 周视图导航（prevWeek/nextWeek）- 保持当前周索引，选择该周可用日期（若有月份变化）
     * 3. 月份/年份变化 - 只有在非周视图导航引起的变化时，才使用默认选择逻辑
     *
     * 这种优先级处理确保周视图的导航体验流畅一致，不会在月份切换时意外跳回第一周
     */

    // 前一个月
    prevMonth() {
      // 设置标志，记录这是否是周视图触发的月份变化
      const isWeekViewMonthChange = !this.isExpanded;
      this.isWeekViewMonthChange = isWeekViewMonthChange;

      if (this.currentMonth === 0) {
        this.currentYear--;
        this.currentMonth = 11;
      } else {
        this.currentMonth--;
      }

      // 如果是从周视图的导航触发的月份变化
      if (isWeekViewMonthChange) {
        this.$nextTick(() => {
          // 获取上个月最后一天是星期几
          const lastDayOfMonth = new Date(
            this.currentYear,
            this.currentMonth + 1,
            0
          ).getDay();

          // 计算上个月有多少周
          const totalWeeks = Math.ceil(
            (this.firstDayOfMonth + this.daysCount) / 7
          );

          // 根据上个月最后一天是否为周六(6)决定显示哪一周
          if (lastDayOfMonth === 6) {
            // 如果最后一天是周六，显示最后一周
            this.currentWeekIndex = totalWeeks - 1;
          } else {
            // 如果最后一天不是周六，说明最后几天已经在当前月第一周显示过
            // 显示倒数第二周
            this.currentWeekIndex = totalWeeks - 2;
          }

          console.log(
            `上个月最后一天是星期${lastDayOfMonth}，选择周索引: ${this.currentWeekIndex}`
          );

          // 优先选择周的第一天，如果不可用则寻找该周第一个可用日期
          this.selectWeekFirstDay(this.currentWeekIndex);
        });
      } else if (this.autoSelectFirstDay) {
        // 非周视图导航情况下，如果配置了自动选择第一天，则选择月份第一个可用日期
        this.$nextTick(() => {
          this.selectFirstDayOfMonth();
        });
      }

      this.$emit("month-change", {
        year: this.currentYear,
        month: this.currentMonth,
        direction: "prev",
      });
    },

    // 下一个月
    nextMonth() {
      // 设置标志，记录这是否是周视图触发的月份变化
      const isWeekViewMonthChange = !this.isExpanded;
      this.isWeekViewMonthChange = isWeekViewMonthChange;

      if (this.currentMonth === 11) {
        this.currentYear++;
        this.currentMonth = 0;
      } else {
        this.currentMonth++;
      }

      // 如果是从周视图的导航触发的月份变化
      if (isWeekViewMonthChange) {
        this.$nextTick(() => {
          // 获取下个月第一天是星期几
          const nextMonthFirstDay = this.firstDayOfMonth;

          // 根据下个月第一天是否为周日(0)决定显示哪一周
          if (nextMonthFirstDay === 0) {
            // 如果第一天是周日，显示第一周
            this.currentWeekIndex = 0;
          } else {
            // 如果第一天不是周日，说明第一周包含上个月的日期
            // 显示第二周
            this.currentWeekIndex = 1;
          }

          console.log(
            `下个月第一天是星期${nextMonthFirstDay}，选择周索引: ${this.currentWeekIndex}`
          );

          // 优先选择周的第一天，如果不可用则寻找该周第一个可用日期
          this.selectWeekFirstDay(this.currentWeekIndex);
        });
      } else if (this.autoSelectFirstDay) {
        // 非周视图导航情况下，如果配置了自动选择第一天，则选择月份第一个可用日期
        this.$nextTick(() => {
          this.selectFirstDayOfMonth();
        });
      }

      this.$emit("month-change", {
        year: this.currentYear,
        month: this.currentMonth,
        direction: "next",
      });
    },

    // 选择上月最后一周的第一个可用日期
    selectLastWeekFirstAvailableDate() {
      // 计算最后一周的起始和结束日期索引
      const weekStartIndex = this.currentWeekIndex * 7;
      const weekEndIndex = weekStartIndex + 6;

      // 计算最后一周中当月的起始日
      let firstDayInCurrentMonth = 0;
      if (weekStartIndex < this.firstDayOfMonth) {
        // 如果周开始于上个月，则当月第一天位于周内的位置
        firstDayInCurrentMonth = 1;
      } else {
        // 周完全在当月内，计算周起始日对应的当月日期
        firstDayInCurrentMonth = weekStartIndex - this.firstDayOfMonth + 1;
      }

      // 确保不超过月份的总天数
      if (firstDayInCurrentMonth > this.daysCount) {
        firstDayInCurrentMonth = this.daysCount;
      }

      // 尝试找到周内第一个可用日期
      for (
        let day = firstDayInCurrentMonth;
        day <= this.daysCount && day - firstDayInCurrentMonth < 7;
        day++
      ) {
        const date = dateHelpers.createDateForMP(
          this.currentYear,
          this.currentMonth,
          day
        );
        if (this.isAvailableDayByDate(date)) {
          this.selectSpecificDate(date);
          return;
        }
      }

      // 如果在最后一周的当月日期中没找到可用日期，尝试查看是否有跨月到下个月的日期
      if (weekEndIndex > this.firstDayOfMonth + this.daysCount - 1) {
        for (
          let i = 1;
          i <= weekEndIndex - (this.firstDayOfMonth + this.daysCount - 1);
          i++
        ) {
          const nextMonth =
            this.currentMonth === 11 ? 0 : this.currentMonth + 1;
          const nextYear =
            this.currentMonth === 11 ? this.currentYear + 1 : this.currentYear;
          const date = dateHelpers.createDateForMP(nextYear, nextMonth, i);

          if (this.isAvailableDayByDate(date)) {
            this.selectSpecificDate(date);
            return;
          }
        }
      }

      // 如果在周内没找到可用日期，选择一个默认日期（当月最后一天）
      const lastDayDate = dateHelpers.createDateForMP(
        this.currentYear,
        this.currentMonth,
        this.daysCount
      );
      this.selectSpecificDate(lastDayDate);
    },

    // 选择当前显示月份的第一天
    selectFirstDayOfMonth() {
      const firstDay = dateHelpers.createDateForMP(
        this.currentYear,
        this.currentMonth,
        1
      );

      // 如果当前已选日期在当前月份内，不需要更改
      if (this.isDateInCurrentMonth(this.startDate)) {
        return;
      }

      // 首先尝试选择第一天
      if (this.isAvailableDayByDate(firstDay)) {
        this.selectSpecificDate(firstDay);
        return;
      }

      // 如果第一天不可选，尝试找到月份中的第一个可选日期
      const daysInMonth = new Date(
        this.currentYear,
        this.currentMonth + 1,
        0
      ).getDate();

      for (let day = 2; day <= daysInMonth; day++) {
        const date = dateHelpers.createDateForMP(
          this.currentYear,
          this.currentMonth,
          day
        );
        if (this.isAvailableDayByDate(date)) {
          this.selectSpecificDate(date);
          break;
        }
      }
    },

    // 选择指定的日期
    selectSpecificDate(date) {
      if (!date) return;

      // 确保传入的日期是有效的
      const validDate = dateHelpers.handleMiniProgramDate(date);
      if (!validDate) return;

      if (this.mode === "single") {
        this.startDate = dateHelpers.createDateForMP(
          validDate.getFullYear(),
          validDate.getMonth(),
          validDate.getDate()
        );
        this.endDate = null;

        // 发出日期选择变化事件
        this.$emit("date-selection-change", {
          date: this.startDate,
          formattedDate: this.formatDate(this.startDate),
          timestamp: this.startDate.getTime(),
          year: this.startDate.getFullYear(),
          month: this.startDate.getMonth(),
          day: this.startDate.getDate(),
        });
      } else {
        // 范围选择模式下，只设置开始日期
        this.startDate = dateHelpers.createDateForMP(
          validDate.getFullYear(),
          validDate.getMonth(),
          validDate.getDate()
        );
        this.endDate = null;
        this.selectionMode = "end";

        // 发出日期选择变化事件
        this.$emit("date-selection-change", {
          startDate: this.startDate,
          endDate: this.endDate,
          formattedStartDate: this.formatDate(this.startDate),
          startTimestamp: this.startDate.getTime(),
          startYear: this.startDate.getFullYear(),
          startMonth: this.startDate.getMonth(),
          startDay: this.startDate.getDate(),
        });
      }
    },

    // 格式化日期为字符串：例如"2023-12-31"
    formatDate(date) {
      if (!date) return "";
      return dateHelpers.formatDate(date, "YYYY-MM-DD");
    },

    // 解析日期字符串为Date对象
    parseDate(dateString) {
      return dateHelpers.parseDate(dateString);
    },

    // 格式化上个月的日期
    formatPrevMonthDate(day) {
      // 计算上个月的年份和月份
      let prevYear = this.currentYear;
      let prevMonth = this.currentMonth - 1;

      if (prevMonth < 0) {
        prevMonth = 11; // 12月
        prevYear--;
      }

      return this.formatDate(
        dateHelpers.createDateForMP(prevYear, prevMonth, day)
      );
    },

    // 格式化下个月的日期 todo
    formatNextMonthDate(day) {
      // 计算下个月的年份和月份
      let nextYear = this.currentYear;
      let nextMonth = this.currentMonth + 1;

      if (nextMonth > 11) {
        nextMonth = 0; // 1月
        nextYear++;
      }

      return this.formatDate(
        dateHelpers.createDateForMP(nextYear, nextMonth, day)
      );
    },

    // 获取单个日期的极简信息，只存储必要的渲染信息
    getDateInfo(day, monthOffset = 0) {
      // 计算真实的月份和年份，处理跨月情况
      let month = this.currentMonth + monthOffset;
      let year = this.currentYear;

      // 处理跨年逻辑
      if (month < 0) {
        month += 12;
        year -= 1;
      } else if (month > 11) {
        month -= 12;
        year += 1;
      }

      // 月份类型标记
      let monthType = "current";
      if (monthOffset < 0) {
        monthType = "prev";
      } else if (monthOffset > 0) {
        monthType = "next";
      }

      // 创建临时日期对象用于判断可用性
      const tempDate = dateHelpers.createDateForMP(year, month, day);
      // 格式化日期 为 YYYY-MM-DD
      const formattedDate = this.formatDate(tempDate); // todo 目前就indicatorInfoList使用formattedDate 批量生成不太好
      // 检查是否有指示器
      const indicatorInfoList = this.getIndicatorInfo(tempDate);

      // 只返回渲染所需的最基本信息
      return {
        day, // 日期数字
        month, // 月份 (0-11)
        year, // 年份
        monthType, // 月份类型：prev, current, next
        isCurrentMonth: monthOffset === 0, // 是否为当前月份
        isAvailable: this.isAvailableDayByDate(tempDate), // 是否可选择
        // 这些状态属性会在updateSelectedStatus中或模板渲染时判断
        isSelected: false,
        isInRange: false,
        formattedDate, // 格式化后的日期，如 "2023-12-31"
        // 指示器相关
        hasIndicator: indicatorInfoList && indicatorInfoList.length > 0,
        //指示器数据
        indicators: indicatorInfoList || [],
        isToday:
          tempDate.getDate() === this.internalTodayDate.getDate() &&
          tempDate.getMonth() === this.internalTodayDate.getMonth() &&
          tempDate.getFullYear() === this.internalTodayDate.getFullYear(),
      };
    },

    // 生成整个月的日历数据（极简版）
    generateCalendarDays() {
      const days = [];

      // 获取当前月第一天是星期几
      const firstDayOfMonth = this.firstDayOfMonth;

      // 1. 添加上个月的日期
      const prevMonthDays = this.getPrevMonthDays();
      for (let i = 0; i < firstDayOfMonth; i++) {
        const day = prevMonthDays - firstDayOfMonth + i + 1;
        // 获取极简的日期信息
        const dateInfo = this.getDateInfo(day, -1); // 月份偏移量为-1
        days.push(dateInfo);
      }

      // 2. 添加当前月的日期
      for (let day = 1; day <= this.daysCount; day++) {
        const dateInfo = this.getDateInfo(day, 0); // 月份偏移量为0
        days.push(dateInfo);
      }

      // 3. 添加下个月的日期以填满日历网格
      // 计算需要添加的下个月天数
      const daysToAdd =
        Math.ceil((firstDayOfMonth + this.daysCount) / 7) * 7 -
        (firstDayOfMonth + this.daysCount);
      for (let day = 1; day <= daysToAdd; day++) {
        const dateInfo = this.getDateInfo(day, 1); // 月份偏移量为1
        days.push(dateInfo);
      }

      // 更新日历数据
      this.calendarDays = days;

      // 处理选中状态更新 - 确保选中状态正确反映在新生成的日历数据中
      this.updateSelectedStatus();

      return days;
    },

    // 更新选中状态 - 在日历数据变化后调用
    updateSelectedStatus() {
      if (!this.startDate || !this.calendarDays.length) return;

      // 获取开始日期和结束日期的年月日信息
      const startYear = this.startDate.getFullYear();
      const startMonth = this.startDate.getMonth();
      const startDay = this.startDate.getDate();

      const endDate = this.endDate;
      const endYear = endDate ? endDate.getFullYear() : null;
      const endMonth = endDate ? endDate.getMonth() : null;
      const endDay = endDate ? endDate.getDate() : null;

      // 更新每个日期的选中状态和范围状态
      this.calendarDays.forEach((dayInfo) => {
        // 判断是否是开始日期
        dayInfo.isSelected =
          dayInfo.day === startDay &&
          dayInfo.month === startMonth &&
          dayInfo.year === startYear;

        // 判断是否是结束日期
        if (
          endDate &&
          dayInfo.day === endDay &&
          dayInfo.month === endMonth &&
          dayInfo.year === endYear
        ) {
          dayInfo.isSelected = true;
        }

        // 判断是否在范围内
        if (endDate) {
          // 创建用于比较的临时日期对象
          const tempDate = dateHelpers.createDateForMP(
            dayInfo.year,
            dayInfo.month,
            dayInfo.day
          );
          const tempTimestamp = tempDate.getTime();

          // 获取开始和结束的时间戳用于比较
          const startTimestamp = this.startDate.getTime();
          const endTimestamp = endDate.getTime();

          dayInfo.isInRange =
            tempTimestamp > startTimestamp && tempTimestamp < endTimestamp;
        } else {
          dayInfo.isInRange = false;
        }
      });
    },

    // 检查上个月的某天是否在当前显示的周内
    isInPrevMonthVisibleWeek(day) {
      if (this.isExpanded) return true;

      // 计算上个月的这一天在日历表中的位置
      // 位置 = 这一天在上个月的位置，从0开始
      const dayPosition =
        day - (this.getPrevMonthDays() - this.firstDayOfMonth + 1);

      // 计算当前选中周的起始和结束位置
      const weekStartIndex = this.currentWeekIndex * 7;
      const weekEndIndex = weekStartIndex + 6;

      // 检查这一天是否在当前周范围内
      return dayPosition >= weekStartIndex && dayPosition <= weekEndIndex;
    },

    // 检查下个月的某天是否在当前显示的周内
    isInNextMonthVisibleWeek(day) {
      if (this.isExpanded) return true;

      // 计算下个月的这一天在日历表中的位置
      // 位置 = 上个月天数 + 当前月天数 + 这一天在下个月的位置(从0开始)
      const dayPosition = this.firstDayOfMonth + this.daysCount + day - 1;

      // 计算当前选中周的起始和结束位置
      const weekStartIndex = this.currentWeekIndex * 7;
      const weekEndIndex = weekStartIndex + 6;

      // 检查这一天是否在当前周范围内
      return dayPosition >= weekStartIndex && dayPosition <= weekEndIndex;
    },

    // 获取日期的指示器信息 todo
    getIndicatorInfo(tempDate) {
      if (!this.markedDates || !this.markedDates.length) return null;
      const formattedDate = this.formatDate(tempDate);

      if (this.multipleIndicators) {
        // 支持多个指示器，查找所有匹配的指示器
        const indicators = this.markedDates
          .filter((item) => {
            return item.date === formattedDate;
          })
          .map((item) => ({ type: item.type || "default" }));

        // 限制显示数量
        return indicators.length > 0
          ? indicators.slice(0, this.maxIndicatorsPerDay)
          : null;
      } else {
        // 单指示器模式，只返回第一个匹配的
        const found = this.markedDates.find((item) => {
          return item.date === formattedDate;
        });

        return found ? [{ type: found.type || "default" }] : null;
      }
    },
  },
};
</script>

<style scoped>
.calendar-container {
  position: relative;
  background-color: #fff;
  /* border-radius: 6px; */
  /* box-shadow: 0 2px 6px rgba(0, 0, 0, 0.1); */
  /* padding: 10px; */
  transition: all 0.3s ease;
  overflow: hidden;
  will-change: max-height;
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica,
    Arial, sans-serif;
  transition: all 0.3s ease;
  /* #ifdef H5 */
  cursor: pointer;
  /* #endif */
}

.calendar-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
}

.month-title {
  font-size: 18px;
  font-weight: 500;
  color: #24292e;
}

.btn {
  padding: 6px 12px;
  background: transparent;
  border: none;
  border-radius: 4px;
  color: #586069;
  transition: all 0.2s ease;
  height: 70rpx;
}

.weekdays {
  display: flex;
  padding: 8px 0;
  border-bottom: 1px solid #eaecef;
  transition: all 0.3s ease;
}

.weekdays-collapsed {
  border-bottom: none;
  padding: 8px 0 4px;
}

.weekday {
  flex: 1;
  text-align: center;
  font-size: 14px;
  color: #6a737d;
}

.days-container {
  position: relative;
  overflow: hidden;
  transition: height 0.3s ease;
}

.days {
  display: flex;
  flex-wrap: wrap;
}

.day {
  position: relative;
  width: calc(100% / 7);
  aspect-ratio: 1; /* 保持正方形 */
  display: flex;
  justify-content: center;
  align-items: center;
  transition: all 0.2s ease;
  box-sizing: border-box;
}

.day:before {
  content: "";
  display: block;
  padding-top: 100%; /* 保持宽高比1:1 */
}

.day-content {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  width: 70rpx;
  height: 70rpx;
  display: flex;
  justify-content: center;
  align-items: center;
  border-radius: 50%;
  font-size: 14px;
  z-index: 1;
}

.current-month .day-content {
  color: #24292e;
}

.prev-month .day-content,
.next-month .day-content {
  color: #ccc;
  background-color: transparent;
}
.calendar-collapsed .prev-month .day-content,
.calendar-collapsed .next-month .day-content {
  color: #24292e;
  background-color: transparent;
}

.unavailable-day .day-content {
  color: #ccc !important;
  background-color: transparent;
  /* 添加划线样式 */
  text-decoration: line-through;

  /* #ifdef H5 */
  cursor: not-allowed;
  /* #endif */
}

.today .day-content {
  border: 1px solid #0366d6;
  color: #0366d6;
}

.in-range .day-content {
  background-color: #dfedf3;
  color: #0366d6;
  border-radius: 0;
}

.in-range.start-date .day-content {
  border-radius: 50% 0 0 50%;
}

.in-range.end-date .day-content {
  border-radius: 0 50% 50% 0;
}

.indicator {
  position: absolute;
  /* #ifdef H5 */
  bottom: 8rpx;
  /* #endif */
  /* #ifndef H5 */
  bottom: 16rpx;
  /* #endif */
  left: 50%;
  transform: translateX(-50%);
  font-size: 8px;
  color: #0366d6;
  z-index: 2;
}

.start-date .indicator,
.end-date .indicator {
  color: white;
}
.single-date .day-content,
.start-date .day-content,
.end-date .day-content {
  background-color: #0366d6;
  color: white;
}
.expand-indicator {
  height: 4px;
  width: 40px;
  background-color: #e1e4e8;
  margin: 8px auto;
  border-radius: 2px;
}

.expand-indicator:hover {
  background-color: #d1d5da;
}

.calendar-footer {
  display: flex;
  justify-content: space-between;
  align-items: center;
  flex-direction: column;
  padding: 12px 16px;
  border-top: 1px solid #eaecef;
}

.date-info {
  display: flex;
  margin: 12rpx 0;
  font-size: 14px;
  color: #24292e;
}

.action-buttons {
  display: flex;
  gap: 8px;
  width: 100%;
}

.reset-btn,
.confirm-btn {
  width: 45%;
  height: 70rpx;
  line-height: 80rpx;
  text-align: center;
  border-radius: 10rpx;
  font-size: 30rpx;
}

.reset-btn {
  background-color: #f5f5f5;
  color: #666;
}

.confirm-btn {
  background-color: #4e6ef2;
  color: #fff;
}

/* 收缩状态的特殊样式 */
.calendar-collapsed .days {
  height: auto;
}

.calendar-collapsing .days {
  transition: height 0.3s ease;
}

/* 周视图中仅显示当前周的日期 */
.calendar-collapsed .day {
  display: none;
}

.calendar-collapsed .day.current-month,
.calendar-collapsed .day.prev-month,
.calendar-collapsed .day.next-month {
  display: flex;
}

/* 确保只有在展开状态下才显示底部 */
.calendar-collapsed .calendar-footer {
  display: none;
}

.day-indicator {
  position: absolute;
  bottom: 5px;
  left: 50%;
  transform: translateX(-50%);
  width: 6px;
  height: 6px;
  border-radius: 50%;
  z-index: 2;
}

/* 多指示器容器 */
.day-indicators-container {
  position: absolute;
  bottom: 4px;
  left: 0;
  right: 0;
  display: flex;
  justify-content: center;
  gap: 3px;
  z-index: 2;
}

/* 多指示器模式下的样式 */
.day-indicators-container .day-indicator {
  position: relative;
  left: auto;
  transform: none;
}

/* 预设样式1: 默认点 - 蓝色 */
.indicator-default {
  background-color: #0366d6;
}

/* 预设样式2: 重要点 - 红色 */
.indicator-primary {
  background-color: #e53e3e;
}

/* 预设样式3: 次要点 - 绿色 */
.indicator-secondary {
  background-color: #38a169;
}

/* 预设样式4: 警告点 - 橙色 */
.indicator-warning {
  background-color: #ed8936;
}
</style>




